package com.gebogebo.android.justads;

import static java.lang.String.format;

import java.util.concurrent.atomic.AtomicInteger;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

import com.greystripe.android.sdk.GSSDK;

/**
 * main activity which fetches and displays ad to users
 *  
 * @author viraj
 */
public class JustAdsActivity extends Activity implements OnClickListener,
        AdEventsListener {
    private static final String lg = "activity";
    private static final int PREF_ACTIVITY_ID = 10;
    //enum indicating ad repositories that are used in this app
    //if you add a new repository here, make sure you handle that repository in adAdds()
    private static enum AD_REPOSITORY {
        ADMOB, MILLENIA, GREYSTRIPE
    };

    //this is used to indicate when progress dialog box should be made invisible
    private AtomicInteger numberOfAdsRequested = new AtomicInteger();
    //indicates that at least one ad was successfully received in last set of requests
    private boolean atleastOneAdReceived = false;
    
    //listeners for ad repositories
    private AdManager adMobManager = null;
    private AdManager milleniaManager = null;

    private ProgressDialog loadingDialog = null;
    private GSSDK gsSdk;
    
    
    //indicates which repository is being currently used to fetch ads
    private AD_REPOSITORY currentAdRepo = null;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gsSdk = GSSDK.initialize(this, "<TODO: add key here>");

        Button button = (Button) findViewById(R.id.exitButton);
        button.setOnClickListener(this);
        button = (Button) findViewById(R.id.refreshButton);
        button.setOnClickListener(this);
        button = (Button) findViewById(R.id.shareButton);
        button.setOnClickListener(this);
        
        initializeManagers();
        addAds();

        Log.i(lg, "loaded everything");
    }
    
    private void initializeManagers() {
        SharedPreferences defPref = PreferenceManager.getDefaultSharedPreferences(this);
        UserPreferences userPref = new UserPreferences(defPref);
        adMobManager = new AdMobManager(userPref, new AdMobAdListener(this));
        milleniaManager = new MilleniaAdManager(userPref, new MilleniaAdListener(this));
    }
    
    /**
     * adds ads to ads view. also starts the "loading" dialog box so that user can't interact with anything
     * on screen
     */
    private void addAds() {
        hideLoadingDialogIfVisible();
        loadingDialog = ProgressDialog.show(this, null, getText(R.string.dialogText));
        //this is the layout where all ads are added
        LinearLayout layout = (LinearLayout) findViewById(R.id.ads);
        layout.removeAllViews(); //remove every view from the parent view

        currentAdRepo = getNextAdRepository(currentAdRepo);
        Log.i(lg, "adding ads for adRepo: " + currentAdRepo);

        switch (currentAdRepo) {
        
            case ADMOB:
                numberOfAdsRequested.set(adMobManager.getAdsPerRequest());
                atleastOneAdReceived = false;
                //limiting number of ads to 3 because of screen size limitation
                adMobManager.requestAd(this, layout);
                break;
            case MILLENIA:
                numberOfAdsRequested.set(milleniaManager.getAdsPerRequest());
                atleastOneAdReceived = false;
                //limiting number of ads to 3 because of screen size limitation
                milleniaManager.requestAd(this, layout);
                break;
            case GREYSTRIPE:
                if (gsSdk.isAdReady()) {
                    Log.i(lg, "gssdk is available");
                    gsSdk.displayAd(this);
                } else {
                    Log.i(lg, "gssdk is not available");
                    addAds();
                }
                break;
            default:
                //should never happen
                break;
        }
    }

    /**
     * hides the "loading" dialog box if it was visible
     */
    private void hideLoadingDialogIfVisible() {
        if (loadingDialog != null && loadingDialog.isShowing()) {
            loadingDialog.hide();
            loadingDialog.dismiss();
            Log.d("activity", "loadingDialog dismissed");
        } else {
            Log.d(lg, "dialog not visible. nothing to hide");
        }
    }

    /**
     * obtains value of next repository value from the repository enum
     * 
     * @param curreRepo repository whose next repository value is to be obtained
     * @return next repository value from the given current repository value
     */
    private AD_REPOSITORY getNextAdRepository(AD_REPOSITORY curreRepo) {
        Log.i(lg, "looking for next repo after: " + curreRepo);
        if (curreRepo == null) {
            return AD_REPOSITORY.values()[0];
        }
        AD_REPOSITORY[] adRepos = AD_REPOSITORY.values();
        int cnt = 0;
        for (AD_REPOSITORY adRepo : adRepos) {
            if (curreRepo.equals(adRepo)) {
                if (cnt >= adRepos.length - 1) {
                    cnt = -1;
                }
                return adRepos[cnt + 1];
            }
            cnt++;
        }
        return adRepos[0]; // unreachable code
    }
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        Log.i(lg, "Options menu created");
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.settings) {
            Log.i(lg, "Settings selected");
            Intent prefIntent = new Intent(Intent.ACTION_EDIT);
            prefIntent.addCategory(getString(R.string.prefsCategory));
            startActivityForResult(prefIntent, PREF_ACTIVITY_ID);
        }
        return true;
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(lg, format("received activity result. request %s, result %s", requestCode, resultCode));
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
            case PREF_ACTIVITY_ID:
                Log.i(lg, "preferences changed");
                initializeManagers();
                break;
            default:
                break;
        }
        switch(resultCode) {
            case GSSDK.GS_ACTIVITY_RESULT:
                Log.i(lg, "GS activity result");
                addAds();
                break;
            default:
                break;
        }
    }

    @Override
    public void onDestroy() {
        if(loadingDialog != null) {
            loadingDialog.dismiss();
        }
        super.onDestroy();
    }

    /* (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    public void onClick(View v) {
        Log.i(lg, "button clicked");
        switch (v.getId()) {
        case R.id.exitButton:
            Log.i(lg, "exit button clicked");
            this.finish();
            break;
        case R.id.refreshButton:
            Log.i(lg, "refresh button clicked");
            addAds();
            break;
        case R.id.shareButton:
            Log.i(lg, "share button clicked");
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.shareMessage));
            startActivity(Intent.createChooser(intent, getString(R.string.shareDialogTitle)));
            break;
        default:
            Log.i(lg, "unknown button clicked");
            break;
        }
    }

    /* (non-Javadoc)
     * @see com.gebogebo.android.justads.AdEventsListener#adReceived()
     */
    public void adReceived() {
        int adsLeft = numberOfAdsRequested.decrementAndGet();
        atleastOneAdReceived = true;
        Log.i(lg, "adReceived() event in activity. number of ads left: " + numberOfAdsRequested);
        if(adsLeft == 0) {
            Log.i(lg, "hiding dialog");
            hideLoadingDialogIfVisible();
        }
    }

    /* (non-Javadoc)
     * @see com.gebogebo.android.justads.AdEventsListener#adFailed()
     */
    public void adFailed() {
        int adsLeft = numberOfAdsRequested.decrementAndGet();
        Log.i("activity", "adFailed() event in activity. number of ads left: " + numberOfAdsRequested);
        // ad failed for last attempt, do it for next repository
        if(adsLeft == 0 && atleastOneAdReceived == false) {
            Log.i("activity", "showing next ads");
            addAds();
        }
    }
}
